<template>
  <cas :data="options" @on-change="handleChange" :loadData="loadOption" transfer>
    <v-combobox
      :label="label"
      :rules="defaultRules"
      chips
      clearable
      v-model="selected"
      multiple
      required
    >
      <template v-slot:selection="{ item }">
        <v-chip
          @click.stop
          v-if="multiple"
          close
          @click:close="remove(item)"
          small
          outlined
          color="green"
        >{{ item.label }}&nbsp;</v-chip>
        <v-chip @click.stop v-else small>{{ item.__label }}</v-chip>
      </template>
    </v-combobox>
  </cas>
</template>

<script>
import { Cascader } from "iview";

export default {
  name: "vCascader",
  components: {
    cas: Cascader
  },
  props: {
    value: {},
    label: {
      type: String
    },
    url: {
      type: String
    },
    itemText: {
      type: String,
      default: "name"
    },
    itemValue: {
      type: String,
      default: "id"
    },
    children: {
      type: String,
      default: "children"
    },
    multiple: {
      type: Boolean,
      default: false
    },
    showAllLevels: {
      type: Boolean,
      default: false
    },
    required: {
      type: Boolean,
      default: false
    },
    rules: {
      type: Array
    }
  },
  data() {
    return {
      options: [],
      selected: [],
      defaultRules: [v => !!v || "Category is required"]
    };
  },
  methods: {
    handleChange(value, selectedData) {
      // console.log("model: ", this.selected);
      // 获取最后一级
      const option = selectedData[selectedData.length - 1];
      // 如果是多选，则默认只保存最后一级选项
      if (this.multiple) {
        // 将最后一级保存到selected中
        if (this.selected.findIndex(o => o.value === option.value) < 0) {
          this.selected.push(option);
        }
        // 返回已选中的值
        // console.log("end: ", this.selected);

        this.$emit("input", this.transfer(this.selected));
      } else {
        // 单选，则需要判断是否需要显示所有级别
        if (this.showAllLevels) {
          // 显示所有级别,将各级别label进行拼接
          this.selected = [option.__label];
          // 返回id数组
          this.$emit("input", this.transfer(selectedData));
        } else {
          // 只显示最后一级
          this.selected = [option.label];
          // 返回
          this.$emit("input", this.transfer([option])[0]);
        }
      }
    },
    loadOption(item, callback) {
      // 延迟加载次级选项
      item.loading = true;
      this.loadData(item.value)
        .then(data => {
          item.children = data;
          item.loading = false;
          callback();
        })
        .catch(() => {
          item.loading = false;
          callback();
        });
    },
    loadData(pid) {
      // 从指定的url地址加载数据，并格式化
      return new Promise(resolve => {
        this.axios
          .get(this.url, {
            params: {
              pid: pid
            }
          })
          .then(resp => {
            const data = [];
            for (let d of resp.data) {
              const node = {
                value: d[this.itemValue],
                label: d[this.itemText]
              };
              if (d.isParent) {
                node["children"] = [];
                node["loading"] = false;
              }
              data.push(node);
            }
            resolve(data);
          });
      });
    },
    remove(item) {
      this.selected = this.selected.filter(o => o.value !== item.value);
      this.$emit("input", this.transfer(this.selected));
    },
    transfer(arr) {
      return arr.map(({ label, value }) => {
        const obj = {};
        obj[this.itemText] = label;
        obj[this.itemValue] = value;
        return obj;
      });
    },
    validate() {
      if (this.required) {
        this.$refs.form.validate();
      }
    }
  },
  created() {
    this.loadData(0).then(data => {
      this.options = data;
      console.log(data);
    });
    if (this.required) {
      this.defaultRules.push(v => v.length > 0 || this.label + "不能为空");
    }
    if (this.rules) {
      this.rules.forEach(r => this.defaultRules.push(r));
    }
  },
  watch: {
    value: {
      deep: true,
      handler(val) {
        console.log(val)
        if (!val) {
          this.selected = [];
          return;
        }
        if (val && this.showAllLevels && !this.multiple) {
          this.selected = [val.map(o => o[this.itemText]).join("/")];
        } else if (this.multiple && val) {
          this.selected = val.map(o => {
            return {
              label: o[this.itemText],
              value: o[this.itemValue]
            };
          });
        } else {
          this.selected = [val[this.itemText]];
        }
      }
    }
  }
};
</script>

<style scoped>
.ivu-cascader-menu-item {
  font-size: 14px;
}
</style>
